package com.lingnan.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lingnan.dto.OptimizationResult;
import com.lingnan.dto.ResumeOptimizeRequest;
import com.lingnan.dto.ResumeOptimizeResponse;

import com.lingnan.entity.Resume;
import com.lingnan.entity.ResumeOptimize;
import com.lingnan.mapper.ResumeMapper;
import com.lingnan.mapper.ResumeOptimizeMapper;
import com.lingnan.service.ResumeOptimizeService;
import lombok.RequiredArgsConstructor;

import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class ResumeOptimizeServiceImpl implements ResumeOptimizeService {

    private final ResumeMapper resumeMapper;
    private final ResumeOptimizeMapper resumeOptimizeMapper;
    private final OpenAiChatModel chatModel;

    private static final String MODEL_VERSION = "deepseek-chat-v1.0";

    @Override
    @Transactional
    public ResumeOptimizeResponse optimizeResume(ResumeOptimizeRequest request) {
        log.info("开始优化简历，resumeId: {}", request.getResumeId());

        // 1. 获取简历信息
        Resume resume = resumeMapper.selectById(request.getResumeId());
        if (resume == null) {
            throw new RuntimeException("简历不存在");
        }

        String content = request.getResumeContent() != null ?
                request.getResumeContent() : resume.getContent();

        // 2. 调用AI进行优化
        OptimizationResult result = callAiForOptimization(content,
                request.getTargetPosition(), request.getTargetIndustry());

        // 3. 保存优化记录
        ResumeOptimize optimize = new ResumeOptimize();
        optimize.setResumeId(request.getResumeId());
        optimize.setOriginalText(content);
        optimize.setOptimizedText(result.getOptimizedContent());
        optimize.setScore(result.getScore());
        optimize.setSuggestions(result.getSuggestions());
        optimize.setModelVersion(MODEL_VERSION);
        // 添加这两行设置时间
        optimize.setCreatedAt(LocalDateTime.now());
//        optimize.setUpdatedAt(LocalDateTime.now());
        resumeOptimizeMapper.insert(optimize);

        // 4. 转换为响应对象
        ResumeOptimizeResponse response = new ResumeOptimizeResponse();
        BeanUtils.copyProperties(optimize, response);
        response.setOptimizeId(optimize.getId());

        log.info("简历优化完成，optimizeId: {}", optimize.getId());
        return response;
    }

    @Override
    public List<ResumeOptimizeResponse> getOptimizeHistory(Long resumeId) {
        List<ResumeOptimize> optimizes = resumeOptimizeMapper.selectList(
                new LambdaQueryWrapper<ResumeOptimize>()
                        .eq(ResumeOptimize::getResumeId, resumeId)
                        .orderByDesc(ResumeOptimize::getCreatedAt)
        );

        return optimizes.stream()
                .map(this::convertToResponse)
                .collect(Collectors.toList());
    }

    @Override
    public ResumeOptimizeResponse getLatestOptimize(Long resumeId) {
        ResumeOptimize optimize = resumeOptimizeMapper.selectOne(
                new LambdaQueryWrapper<ResumeOptimize>()
                        .eq(ResumeOptimize::getResumeId, resumeId)
                        .orderByDesc(ResumeOptimize::getCreatedAt)
                        .last("LIMIT 1")
        );

        return optimize != null ? convertToResponse(optimize) : null;
    }

    @Override
    @Transactional
    public ResumeOptimizeResponse reOptimize(Long resumeId, String targetPosition) {
        Resume resume = resumeMapper.selectById(resumeId);
        if (resume == null) {
            throw new RuntimeException("简历不存在");
        }

        ResumeOptimizeRequest request = new ResumeOptimizeRequest();
        request.setResumeId(resumeId);
        request.setResumeContent(resume.getContent());
        request.setTargetPosition(targetPosition);

        return optimizeResume(request);
    }

    private OptimizationResult callAiForOptimization(String content,
                                                     String targetPosition, String targetIndustry) {

        String prompt = buildOptimizationPrompt(content, targetPosition, targetIndustry);

        try {
            String response = chatModel.call(prompt);
            return parseAiResponse(response);

        } catch (Exception e) {
            log.error("AI优化调用失败", e);
            throw new RuntimeException("AI服务调用失败，请稍后重试");
        }
    }

    private String buildOptimizationPrompt(String content, String targetPosition, String targetIndustry) {
        StringBuilder prompt = new StringBuilder();
        prompt.append("请作为专业的简历优化专家，对以下简历进行优化分析：\n\n");
        prompt.append("原始简历内容：\n").append(content).append("\n\n");

        if (targetPosition != null && !targetPosition.trim().isEmpty()) {
            prompt.append("目标职位：").append(targetPosition).append("\n");
        }

        if (targetIndustry != null && !targetIndustry.trim().isEmpty()) {
            prompt.append("目标行业：").append(targetIndustry).append("\n");
        }

        prompt.append("\n请按照以下JSON格式返回优化结果：\n");
        prompt.append("{\n");
        prompt.append("  \"optimizedContent\": \"优化后的简历内容\",\n");
        prompt.append("  \"score\": 85.5,\n");
        prompt.append("  \"suggestions\": \"具体的优化建议，包括：1.技能关键词优化 2.工作经历描述优化 3.项目经验突出 4.其他建议\"\n");
        prompt.append("}\n\n");
        prompt.append("注意：\n");
        prompt.append("1. 评分范围0-100分\n");
        prompt.append("2. 优化内容要保持原有信息的真实性\n");
        prompt.append("3. 建议要具体可操作\n");
        prompt.append("4. 返回严格的JSON格式");

        return prompt.toString();
    }

    private OptimizationResult parseAiResponse(String response) {
        try {
            // 清理响应格式
            response = response.trim();
            if (response.startsWith("```json")) {
                response = response.substring(7);
            }
            if (response.endsWith("```")) {
                response = response.substring(0, response.length() - 3);
            }
            response = response.trim();

            // 使用Jackson解析JSON
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode jsonNode = objectMapper.readTree(response);

            OptimizationResult result = new OptimizationResult();
            result.setOptimizedContent(jsonNode.get("optimizedContent").asText());
            result.setScore(new BigDecimal(jsonNode.get("score").asText()));
            result.setSuggestions(jsonNode.get("suggestions").asText());
            result.setModelVersion(MODEL_VERSION);

            log.info("JSON解析成功 - score: {}", result.getScore());
            return result;

        } catch (Exception e) {
            log.error("解析AI响应失败，原始响应: {}", response, e);
            // 返回默认结果
            OptimizationResult result = new OptimizationResult();
            result.setOptimizedContent("AI优化服务暂时不可用，请稍后重试");
            result.setScore(new BigDecimal("0"));
            result.setSuggestions("服务异常，建议稍后重试");
            result.setModelVersion(MODEL_VERSION);
            return result;
        }
    }

    private String extractJsonValue(String json, String key) {
        String pattern = "\"" + key + "\"\\s*:\\s*";
        int start = json.indexOf(pattern);
        if (start == -1) return "";

        start = json.indexOf("\"", start + pattern.length());
        if (start == -1) return "";
        start++;

        int end = json.indexOf("\"", start);
        while (end != -1 && json.charAt(end - 1) == '\\') {
            end = json.indexOf("\"", end + 1);
        }

        return end != -1 ? json.substring(start, end) : "";
    }

    private ResumeOptimizeResponse convertToResponse(ResumeOptimize optimize) {
        ResumeOptimizeResponse response = new ResumeOptimizeResponse();
        BeanUtils.copyProperties(optimize, response);
        response.setOptimizeId(optimize.getId());
        return response;
    }
}